import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:image_pickers/image_pickers.dart';
import 'package:xindong/common/xindong_all.dart';
import 'package:xindong/common/xindong_methods.dart';
import 'package:xindong/extension/extension_string.dart';
import 'package:xindong/manager/network/xindong_networking.dart';
import 'package:xindong/manager/xindong_permission_ctr.dart';
import 'package:xindong/models/xindong_file_select_class.dart';
import 'package:xindong/utils/xindong_text_util.dart';
import 'package:xindong/widgets/dialog/xindong_options_sheet.dart';

class ImageUtil {
  // 获取本地icons文件夹资源
  static Image asset(String name, {BoxFit fit = BoxFit.scaleDown, Color? color, double? width, double? height}) {
    return Image.asset(
      name,
      fit: fit,
      color: color,
      width: width,
      height: height,
      excludeFromSemantics: true,
      //去除图片语义
      gaplessPlayback: true, //重新加载图片的过程中，原图片的展示是否保留
    );
  }

  // 获取网络缓存头像
  static Widget avatarUrl(String? imageUrl, {BoxFit fit = BoxFit.cover, Widget? placeholder, bool isZoom = true}) {
    return networkImageUrl(
      imageUrl,
      fit: fit,
      isZoom: isZoom,
      errorWidget: XinDongAll.instance.defaultAvatar,
      placeholder: placeholder,
    );
  }

  // 获取网络缓存图片
  static Widget networkImageUrl(String? imageUrl,
      {BoxFit fit = BoxFit.cover,
      Widget? placeholder,
      Widget? errorWidget,
      double width = double.infinity,
      double height = double.infinity,
      bool isZoom = true,
      double opacity = 1.0,
      int zoomSize = 80}) {
    if (TextUtil.isEmpty(imageUrl) || imageUrl == "null") {
      return errorWidget ??= XinDongAll.instance.defaultImage;
    }
    if (!imageUrl!.contains("http")) {
      imageUrl = XinDongNetworking.instance.fileUrl + imageUrl;
    }
    if (isZoom) {
      // 如果已经包含压缩命令就不处理 png 不做处理
      if (!imageUrl.contains('iopcmd=convert') && imageUrl.contains('jpg')) {
        // 如果包含了其他图片处理(水印...)，就拼接
        if (imageUrl.contains('?iopcmd')) {
          imageUrl = "$imageUrl|iopcmd=convert&dst=jpg&Q=$zoomSize";
        } else {
          imageUrl = "$imageUrl?iopcmd=convert&dst=jpg&Q=$zoomSize";
        }
      }
    }
    try {
      return CachedNetworkImage(
        imageUrl: imageUrl ?? "",
        width: width,
        height: height,
        useOldImageOnUrlChange: true,
        fadeInDuration: Duration.zero,
        fadeOutDuration: Duration.zero,
        placeholderFadeInDuration: Duration.zero,
        imageBuilder: (context, imageProvider) => Container(
          decoration: BoxDecoration(
            image: DecorationImage(image: imageProvider, fit: fit, opacity: opacity),
          ),
        ),
        placeholder: (context, url) => placeholder ??= XinDongAll.instance.defaultImage,
        errorWidget: (context, url, error) => errorWidget ??= XinDongAll.instance.defaultImage,
      );
    } catch (e) {
      return errorWidget ??= XinDongAll.instance.defaultImage;
    }
  }

  /// --------------------------------------------------------
  // 选择头像图片(拍照、从相册选择，正方形)
  static Future<File?> selectAvatar() async {
    File? imageFile;
    final index = await XinDongOptionsSheet.showAwait(dataList: const ["拍照", "从相册获取"]);
    if (index == 0) {
      imageFile = await takePhoto(square: true);
    } else if (index == 1) {
      List<File>? files = await selectPhotos(maxCount: 1, square: true);
      if (files != null && files.length == 1) {
        imageFile = files.first;
      }
    }
    return imageFile;
  }

  // 选择视频
  static Future<Media?> selectVideo() async {
    bool result = await XinDongPermissionCtr.checkPermission(XinDongAppPermission.videos);
    if (!result) {
      return null;
    }
    List<Media> imageObjects = await ImagePickers.pickerPaths(
      selectCount: 1,
      galleryMode: GalleryMode.video,
      compressSize: 1024 * 10,
      // kb
      videoSelectMaxSecond: 60,
      // 60秒
      uiConfig: UIConfig(uiThemeColor: Colors.black87),
    );
    if (imageObjects.length == 1) {
      return imageObjects.first;
    }
    return null;
  }

  // 选择多张图片(从相册选择)
  static Future<List<File>?> selectPhotos({int maxCount = 8, bool square = false}) async {
    bool result = await XinDongPermissionCtr.checkPermission(XinDongAppPermission.photos);
    if (!result) {
      return null;
    }
    // 相册获取
    List<Media> imageObjects = await ImagePickers.pickerPaths(
      selectCount: maxCount,
      compressSize: 2048,
      galleryMode: GalleryMode.image,
      uiConfig: UIConfig(uiThemeColor: Colors.black87),
      cropConfig: CropConfig(enableCrop: square, width: 1, height: 1),
    );
    if (imageObjects.isEmpty) {
      return null;
    }
    return List<File>.from(imageObjects.map((e) => File(e.path!)));
  }

  // 拍照获取图片
  static Future<File?> takePhoto({bool square = false}) async {
    bool result = await XinDongPermissionCtr.checkPermission(XinDongAppPermission.camera);
    if (!result) {
      return null;
    }
    // 拍照
    Media? imageObject = await ImagePickers.openCamera(
      compressSize: 2048, // 最大内存KB，限2MB
      cameraMimeType: CameraMimeType.photo,
      cropConfig: CropConfig(enableCrop: square, width: 1, height: 1),
    );
    if (imageObject == null) return null;
    return File(imageObject.path!);
  }

  // 获取图片尺寸
  // return [width, height]
  static Future<Size> getImageSizeWithUrl(String url) async {
    var completer = Completer();
    Image imageObject = Image.network(url);
    // 预先获取图片信息
    imageObject.image.resolve(const ImageConfiguration()).addListener(
          ImageStreamListener((ImageInfo info, bool _) {
            completer.complete(Size(info.image.width.toDouble(), info.image.height.toDouble()));
          }, onError: (Object exception, StackTrace? stackTrace) {
            completer.complete(Size.zero);
          }),
        );
    return await completer.future.whenComplete(() => mDebugPrint("Complete"));
  }

  // 获取图片尺寸
  static Future<XinDongSelectFileClass> getImageSizeWithFile(File file) async {
    XinDongSelectFileClass model = XinDongSelectFileClass(file);
    var completer = Completer();
    Image imageObject = Image.file(file);
    // 预先获取图片信息
    imageObject.image.resolve(const ImageConfiguration()).addListener(
          ImageStreamListener((ImageInfo info, bool _) {
            model.width = info.image.width;
            model.height = info.image.height;
            completer.complete(model);
          }, onError: (Object exception, StackTrace? stackTrace) {
            completer.complete(model);
          }),
        );
    return await completer.future.whenComplete(() => mDebugPrint("Complete"));
  }

  // // 根据链接获取图片尺寸比例
  // //
  // // imageUrl 图片链接
  // // start 开始字符串
  // // end 结束字符串
  // // splitChar 分割字符（默认"x"）
  // // scale 比例（默认0.86）
  // // limitScale 限制比例（避免高度占满屏）
  static double imageSizeAspectRatioFromUrl({
    required String imageUrl,
    required String start,
    required String end,
    String splitChar = "x",
    double defaultScale = 0.86,
    double limitScale = 2.0 / 3.0,
  }) {
    try {
      if (imageUrl.contains(start) && imageUrl.contains(end)) {
        int startIndex = imageUrl.indexOf(start) + start.length;
        int endIndex = imageUrl.indexOf(end);
        String sizeText = imageUrl.substring(startIndex, endIndex);
        List list = sizeText.stringToList(pattern: splitChar);
        int width = int.parse(list.first);
        int height = int.parse(list.last);
        defaultScale = max(limitScale, width / height);
      }
    } catch (e) {
      mCatchPrint(e);
    }
    return defaultScale;
  }

  static List<double> imageSizeAspectRatioFromUrlList({
    required String imageUrl,
    required String start,
    required String end,
    String splitChar = "x",
    double scale = 1.0,
    double limitScale = 2.0 / 3.0,
  }) {
    try {
      if (imageUrl.contains(start) && imageUrl.contains(end)) {
        int startIndex = imageUrl.indexOf(start) + start.length;
        int endIndex = imageUrl.indexOf(end);
        String sizeText = imageUrl.substring(startIndex, endIndex);
        List list = sizeText.stringToList(pattern: splitChar);
        int width = int.parse(list.first);
        int height = int.parse(list.last);
        scale = max(limitScale, width / height);
        return [scale, width.toDouble(), height.toDouble()];
      }
    } catch (e) {
      mCatchPrint(e);
    }
    return [scale, 100, 100];
  }
}
